﻿#region 命名空间

using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using Microsoft.Practices.Unity.InterceptionExtension;


#endregion

namespace Sharp.Infrastructure.Crosscutting
{
    /// <summary>
    ///     缓存
    /// </summary>
    [ConfigurationElementType(typeof (CustomCallHandlerData))]
    public class CacheHandler : ICallHandler
    {
        /// <summary>
        ///     构造函数，此构造函数是用于Attribute调用
        /// </summary>
        /// <param name="key">缓存标识</param>
        public CacheHandler(string key)
        {
            Key = key;
        }

        /// <summary>
        ///     构造函数，此处不可省略，否则会导致异常
        /// </summary>
        /// <param name="attributes">配置文件中所配置的参数</param>
        public CacheHandler(NameValueCollection attributes)
        {
            Order = Convert.ToInt32(attributes["Order"]);
            Key = String.IsNullOrEmpty(attributes["Key"]) ? "" : attributes["Key"];
        }

        /// <summary>
        ///     关键字
        /// </summary>
        public string Key { get; set; }

        /// <summary>
        ///     实现ICallHandler.Invoke方法，用于对具体拦截方法做相应的处理
        /// </summary>
        /// <param name="input"></param>
        /// <param name="getNext"></param>
        /// <returns></returns>
        [DebuggerStepThrough]
        public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
        {
            //检查参数是否存在
            if (input == null) throw new ArgumentNullException(nameof(input));
            if (getNext == null) throw new ArgumentNullException(nameof(getNext));

            if (Key.IsNullOrEmpty())
            {
                Key = CreateCacheKey(input.MethodBase, input.Inputs);
            }

            object value;
            if (CacheHelper.TryGet(Key, out value))
            {
                return input.CreateMethodReturn(value, new object[] {input.Arguments});
            }
            else
            {
                //调用具体方法
                var result = getNext()(input, getNext);

                ////如果是bool则判断返回值是否为自定义的消息体
                if (result.ReturnValue != null)
                {
                    CacheHelper.Add(Key, result.ReturnValue, 3600);
                }

                return result;
            }
        }

        /// <summary>
        ///     执行顺序
        /// </summary>
        public int Order { get; set; }

        private string CreateCacheKey(MethodBase methodBase, IParameterCollection pc)
        {
            List<string> pcs = new List<string>();
            for (var i = 0; i < pc.Count; i++)
            {
                pcs.Add(pc.ParameterName(i));
            }

            string key = string.Format("{0}.{1}",
                methodBase.ReflectedType.Namespace,
                methodBase.Name
                );
            if (pcs.Any())
            {
                key = key + "_" + string.Join("-", pcs);
            }
            return key;
        }
    }
}